package gateway.rule.inbound;

import gateway.api.annotation.GatewayType;
import gateway.api.annotation.Named;
import gateway.api.engine.Inbound;
import gateway.api.message.HttpMessage;
import gateway.api.message.Message;
import gateway.rule.path.AntPathMatcher;
import gateway.rule.path.PathMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * @author Jin Zheng
 * @since 2020-09-20
 */
@Named(value = "httpPathInbound", type = GatewayType.HTTP)
public class HttpPathInbound implements Inbound
{
	private static Logger logger = LoggerFactory.getLogger(HttpPathInbound.class);
	public static final String BRACE_START = "{";
	public static final String BRACE_END = "}";
	public static final String PATH = "path";
	public static final String METHOD = "method";

	private PathMatcher matcher = new AntPathMatcher();
	private Map<String, String> args;

	public HttpPathInbound()
	{
	}

	@Override
	public boolean match(Message message)
	{
		if (!(message instanceof HttpMessage))
			return false;

		HttpMessage httpMessage = (HttpMessage) message;
		String path = args.get(PATH);
		String method = args.get(METHOD);
		logger.debug("patten, url: {}, method: {}, actual, path: {}, method: {}",
				path, method, httpMessage.url(), httpMessage.method());

		if (!this.method(method, httpMessage))
			return false;

		if (path == null || path.isEmpty())
			return true;

		if (path.contains(BRACE_START) && path.contains(BRACE_END))
		{
			if (!matcher.match(path, httpMessage.url()))
				return false;

			Map<String, String> map = matcher.extractUriTemplateVariables(path, httpMessage.url());
			httpMessage.pathMap().putAll(map);
		}
		else
		{
			if (!path.equalsIgnoreCase(httpMessage.url()))
				return false;
		}
		return true;
	}

	private boolean method(String method, HttpMessage message)
	{
		if (method == null || method.isEmpty())
			return true;

		return method.equalsIgnoreCase(message.method());
	}

	@Override
	public void setArgs(Map<String, String> args)
	{
		this.args = args;
	}
}
